package com.tbit.common.entity.vo;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 运营报表-新，概况，数据返回vo
 *
 * @author: qiu.longjie
 * @create: 2025-05-21
 */
@Data
@Accessors(chain = true)
public class OperationReportRespBoxVo {

    /**
     * 车辆总数
     */
    private DataBox<Integer> totalMachine;

    /**
     * 已投放车辆数
     */
    private DataBox<Integer> putInTotalMachine;

    /**
     * 可运营车辆数
     */
    private DataBox<Integer> operationalMachine;

    /**
     * 不可运营车辆数
     */
    private DataBox<Integer> unOperationalMachine;

    /**
     * 故障车辆数
     */
    private DataBox<Integer> faultMachine;

    /**
     * 订单车辆数
     */
    private DataBox<Integer> orderMachine;

    /**
     * 有效订单车辆数
     */
    private DataBox<Integer> validOrderMachine;

    /**
     * 车辆投放率
     */
    private DataBox<Double> machinePutInRate;

    /**
     * 车辆可用率
     */
    private DataBox<Double> machineAvailableRate;

    /**
     * 车辆故障率
     */
    private DataBox<Double> machineFaultRate;

    /**
     * 车辆骑行率
     */
    private DataBox<Double> machineRidingRate;

    /**
     * 车辆有效骑行率
     */
    private DataBox<Double> machineValidRidingRate;

    /**
     * 3天无订单车辆数
     */
    private DataBox<Integer> threeDaysNoOrderMachine;

    /**
     * 7天无订单车辆数
     */
    private DataBox<Integer> sevenDaysNoOrderMachine;

    /**
     * 15天无订单车辆数
     */
    private DataBox<Integer> fifteenDaysNoOrderMachine;

    /**
     * 3天无订单车辆率
     */
    private DataBox<Double> threeDaysNoOrderRate;

    /**
     * 7天无订单车辆率
     */
    private DataBox<Double> sevenDaysNoOrderRate;

    /**
     * 15天无订单车辆率
     */
    private DataBox<Double> fifteenDaysNoOrderRate;

    /**
     * 应收订单金额
     */
    private DataBox<Double> totalOrderAmount;

    /**
     * 应收订单数
     */
    private DataBox<Integer> totalOrderCount;

    /**
     * 实收订单金额
     */
    private DataBox<Double> totalReceiptOrderAmount;

    /**
     * 实收订单数
     */
    private DataBox<Integer> totalReceiptOrderCount;

    /**
     * 退款金额
     */
    private DataBox<Double> refundAmount;

    /**
     * 退款订单数
     */
    private DataBox<Integer> refundOrderCount;

    /**
     * 骑行卡收入金额
     */
    private DataBox<Double> ridingCardIncomeAmount;

    /**
     * 骑行卡收入订单数
     */
    private DataBox<Integer> ridingCardIncomeOrderCount;

    /**
     * 期末总预存款金额
     */
    private DataBox<Double> totalPreDepositAmount;

    /**
     * 应收车均收益
     */
    private DataBox<Double> totalMachineAgv;

    /**
     * 实收车均收益
     */
    private DataBox<Double> totalReceiptMachineAgv;

    /**
     * 应收车均单量
     */
    private DataBox<Double> totalOrderPerMachine;

    /**
     * 实收车均单量
     */
    private DataBox<Double> totalReceiptOrderPerMachine;

    /**
     * 应收车均里程
     */
    private DataBox<Double> totalDistancePerMachine;

    /**
     * 实收车均里程
     */
    private DataBox<Double> totalReceiptDistancePerMachine;

    /**
     * 应收车均时长
     */
    private DataBox<Double> totalTimePerMachine;

    /**
     * 实收车均时长
     */
    private DataBox<Double> totalReceiptTimePerMachine;

    /**
     * 总用户数
     */
    private DataBox<Integer> totalUserCount;

    /**
     * 新增用户数
     */
    private DataBox<Integer> newUserCount;

    /**
     * 骑行用户数
     */
    private DataBox<Integer> ridingUserCount;

    /**
     * 3天未骑行用户数
     */
    private DataBox<Integer> threeDaysNoRidingUserCount;

    /**
     * 7天未骑行用户数
     */
    private DataBox<Integer> sevenDaysNoRidingUserCount;

    /**
     * 15天未骑行用户数
     */
    private DataBox<Integer> fifteenDaysNoRidingUserCount;

    /**
     * 新用户7日留存率
     */
    private DataBox<Double> newUserSevenDayRetentionRate;

    /**
     * 总扫码次数
     */
    private DataBox<Integer> totalScanCodeCount;

    /**
     * 总开锁次数
     */
    private DataBox<Integer> totalUnlockCount;

    /**
     * 开锁成功次数
     */
    private DataBox<Integer> successUnlockCount;

    /**
     * 有效骑行次数
     */
    private DataBox<Integer> validOrderCount;

    /**
     * 骑行失败次数
     */
    private DataBox<Integer> failUnlockCount;

    /**
     * 丢单次数
     */
    private DataBox<Integer> lostOrderCount;

    /**
     * 总换电次数
     */
    private DataBox<Integer> totalPowerChangeCount;

    /**
     * 总挪车次数
     */
    private DataBox<Integer> totalMoveCount;

    /**
     * 总调度次数
     */
    private DataBox<Integer> totalDispatchCount;

    /**
     * 总维修次数
     */
    private DataBox<Integer> totalRepairCount;

    /**
     * 换电有效率
     */
    private DataBox<Double> powerChangeEfficiencyRate;

    /**
     * 挪车完成率
     */
    private DataBox<Double> moveCompleteRate;

    /**
     * 调度有效率
     */
    private DataBox<Double> dispatchEfficiencyRate;

    /**
     * 维修完成率
     */
    private DataBox<Double> repairCompleteRate;

    /**
     * 调度后12小时成单率
     */
    private DataBox<Double> dispatchAfter12HoursHasOrderRate;

    public static OperationReportRespBoxVo empty() {
        return new OperationReportRespBoxVo().nullData();
    }

    /**
     * 将所有属性设置为逻辑默认值（Integer为0，Double为0.00D），用于空数据初始化。
     *
     * @return OperationReportRespVo 当前对象
     */
    public OperationReportRespBoxVo nullData() {
        try {
            // 明确指定操作当前类，防止子类干扰
            Class<?> clazz = OperationReportRespBoxVo.class;
            Field[] fields = clazz.getDeclaredFields();
            Map<String, Method> methodMap = Arrays.stream(clazz.getDeclaredMethods())
                    .filter(m ->
                            m.getName().startsWith("set")
                            && m.getParameterCount() == 1
                            && m.getParameterTypes()[0] == DataBox.class
                    )
                    .collect(Collectors.toMap(Method::getName, m -> m, (m1, m2) -> m1));
            for (Field field : fields) {
                java.lang.reflect.Type genericType = field.getGenericType();
                if (!(genericType instanceof ParameterizedType)) {
                    continue;
                }
                java.lang.reflect.Type actualType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
                String setterName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Method setter = methodMap.get(setterName);
                if (setter == null) {
                    continue;
                }
                Object defaultValue;
                if (actualType == Integer.class) {
                    defaultValue = DataBox.empty(Integer.class);
                } else if (actualType == Double.class) {
                    defaultValue = DataBox.empty(Double.class);
                } else {
                    defaultValue = DataBox.empty(Object.class);
                }
                setter.invoke(this, defaultValue);
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化空数据失败", e);
        }
        return this;
    }

    /**
     * OperationReportRespVo集合数据转为OperationReportRespBoxVo数据
     * <p/>
     * 此方法要求OperationReportRespBoxVo的所有属性名称都与OperationReportRespVo的一一对应相同，并且setter方法的参数类型为DataBox。
     *
     * @param operationReportRespVos
     * @return
     */
    public OperationReportRespBoxVo convert(List<OperationReportRespVo> operationReportRespVos) {
        if (CollectionUtils.isEmpty(operationReportRespVos)) {
            OperationReportRespBoxVo.empty();
        }
        //operationReportRespBoxVo.setTotalMachine(new DataBox<Integer>().setWeekData(operationReportRespVos.stream().map(OperationReportRespVo::getTotalMachine).collect(Collectors.toList())));
        //operationReportRespBoxVo.setPutInTotalMachine(new DataBox<Integer>().setWeekData(operationReportRespVos.stream().map(OperationReportRespVo::getPutInTotalMachine).collect(Collectors.toList())));
        // ... 所有属性进行赋值

        // 获取OperationReportRespVo所有 getter 方法对应的字段名
        Map<String, java.lang.reflect.Method> getterMap = Arrays.stream(OperationReportRespVo.class.getMethods())
                .filter(m -> m.getName().startsWith("get") && m.getParameterCount() == 0)
                .collect(Collectors.toMap(
                        Method::getName,
                        Function.identity(),
                        (m1, m2) -> m1
                ));

        // 遍历 OperationReportRespBoxVo 的所有 setter 方法
        Arrays.stream(OperationReportRespBoxVo.class.getMethods())
                .filter(m -> m.getName().startsWith("set") && m.getParameterCount() == 1 && m.getParameterTypes()[0] == DataBox.class)
                .forEach(setter -> {
                    try {
                        // 属性名称提取，去掉 "set" 前缀
                        String fieldName = setter.getName().substring(3); // remove "set"
                        // 获取对应的 getter 方法名称，例如 "getTotalMachine"
                        String getterName = "get" + fieldName;
                        // 获取OperationReportRespVo对应的 getter 方法
                        Method getter = getterMap.get(getterName);
                        if (getter != null) {
                            // 构造 DataBox 并调用 setter
                            // 提取 OperationReportRespVo 中对应字段的值列表
                            List<Object> dataList = operationReportRespVos.stream()
                                    .map(vo -> {
                                        try {
                                            return getter.invoke(vo);
                                        } catch (Exception e) {
                                            return null;
                                        }
                                    })
                                    .collect(Collectors.toList());
                            if (!dataList.isEmpty()) {
                                // dataList中的类型
                                if (dataList.get(0) instanceof Integer) {
                                    DataBox<Integer> dataBox = new DataBox<>();
                                    dataBox.setWeekData(dataList.stream().map(o -> Integer.parseInt(o.toString())).collect(Collectors.toList()));
                                    setter.invoke(this, dataBox);
                                } else if (dataList.get(0) instanceof Double) {
                                    DataBox<Double> dataBox = new DataBox<>();
                                    dataBox.setWeekData(dataList.stream().map(o -> Double.parseDouble(o.toString())).collect(Collectors.toList()));
                                    setter.invoke(this, dataBox);
                                } else {
                                    DataBox<Object> dataBox = new DataBox<>();
                                    dataBox.setWeekData(dataList);
                                    setter.invoke(this, dataBox);
                                }
                            }
                        }

                    } catch (Exception e) {
                        throw new RuntimeException("OperationReportRespVo集合数据转为OperationReportRespBoxVo数据失败", e);
                    }
                });
        return this;
    }

    public static void main(String[] args) {
        System.out.println(OperationReportRespBoxVo.empty());
    }
}
